/**
 * @file main.c
 * @author lcz (you@domain.com)
 * @brief
 * @version 0.1
 * @date 2022-11-15
 *
 * @copyright Copyright (c) 2022
 *
 */
#include <stdio.h>
#include <stdlib.h>

enum
{
   Num
};
int token;
int token_val;
char *src;

/**
 * @brief 词法分析 获取下一个数值
 */
void next()
{
   // skip white space
   while (*src == ' ' || *src == '\t')
   {
      src++;
   }

   token = *src++;

   if (token >= '0' && token <= '9')
   {
      token_val = token - '0';
      token = Num;

      while (*src >= '0' && *src <= '9')
      {
         token_val = token_val * 10 + *src - '0';
         src++;
      }
      return;
   }
}
/**
 * @brief 匹配当前token是否是tk，否报错，是则获取下一个token
 * @param tk 将要进行匹配的token值
 */
void match(int tk)
{
   if (token != tk)
   {
      printf("expected token: %d(%c), got: %d(%c)\n", tk, tk, token, token);
      exit(-1);
   }
   next();
}
// 函数的前置声明
int expr();

/**
 * @brief 括号及数值处理
 * @return * int  数值或（expr）的值
 */
int factor()
{
   int value = 0;
   if (token == '(')
   {
      match('(');
      value = expr();
      match(')');
   }
   else
   {
      value = token_val;
      match(Num);
   }
   return value;
}
/**
 * @brief 项处理，处理*与/,避免右递归增加的中间文法
 *
 * @param lvalue
 * @return * int
 */
int term_tail(int lvalue)
{
   if (token == '*')
   {
      match('*');
      int value = lvalue * factor();
      return term_tail(value);
   }
   else if (token == '/')
   {
      match('/');
      int value = lvalue / factor();
      return term_tail(value);
   }
   else
   {
      return lvalue;
   }
}
/**
 * @brief 项处理
 *
 * @return * int
 */
int term()
{
   int lvalue = factor();
   return term_tail(lvalue);
}
/**
 * @brief 中间文法，避免expr右递归，处理+与-
 *
 * @param lvalue
 * @return * int
 */
int expr_tail(int lvalue)
{
   if (token == '+')
   {
      match('+');
      int value = lvalue + term();
      return expr_tail(value);
   }
   else if (token == '-')
   {
      match('-');
      int value = lvalue - term();
      return expr_tail(value);
   }
   else
   {
      return lvalue;
   }
}
/**
 * @brief 文法的开始 表达式expr
 *
 * @return * int
 */
int expr()
{
   int lvalue = term();
   return expr_tail(lvalue);
}

int main(int argc, char *argv[])
{
   char temp[1024];
   // 标准输入计算表达式
   printf("Enter q to exit the calculator!\n");
   printf(" - (negative sign) is not supported.\n");
   printf("For example, - 3 should be expressed as (0-3).\n");
   printf("Floating point numbers are not supported!\n");
   while (1)
   {
      printf("Please enter an expression! \n>> ");
      scanf("%s", &temp[0]);
      src = &temp[0];
      if(*src=='q'){
         break;
      }
      next();
      printf("result as follows:\n");
      printf("%d\n", expr());
   }

   return 0;
}
